﻿
namespace Patterns4Net.ArchitectureExplorer.ViewModels
{
    using System.ComponentModel.Composition;
    using System.IO;
    using System.Text;
    using Caliburn.Micro;
    using Infrastructure;

    [Export(typeof(OutputWindowViewModel))]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public class OutputWindowViewModel : PropertyChangedBase
    {
        private readonly IDispatcher dispatcher;

        [ImportingConstructor]
        public OutputWindowViewModel(IDispatcher dispatcher)
        {
            this.dispatcher = dispatcher;
        }

        private string content;

        public string OutputContent
        {
            get
            {
                return this.content;
            }
            private set
            {
                this.content = value;
                this.NotifyOfPropertyChange(() => this.OutputContent);
            }
        }

        public TextWriter GetWriter()
        {
            return new OutputWindowWriter(this);
        }

        private class OutputWindowWriter : TextWriter
        {
            private readonly OutputWindowViewModel parent;

            public OutputWindowWriter(OutputWindowViewModel parent)
            {
                this.parent = parent;
            }

            public override Encoding Encoding
            {
                get { return Encoding.UTF8; }
            }

            /// <summary>
            /// This method is called by all other 'Write' methods by the base class.
            /// </summary>
            /// <param name="value"></param>
            public override void Write(char value)
            {
                this.parent.dispatcher.BeginInvoke(() => this.parent.OutputContent += value);
            }

            /// <summary>
            /// This method is overridden just to provide some performance enhancement.
            /// </summary>
            public override void WriteLine(string format)
            {
                this.parent.dispatcher.BeginInvoke(() => this.parent.OutputContent += format + '\n');
            }

            /// <summary>
            /// This method is overridden just to provide some performance enhancement.
            /// </summary>
            public override void WriteLine(string format, object arg0)
            {
                this.parent.dispatcher.BeginInvoke(() => this.parent.OutputContent += string.Format(format, arg0) + '\n');
            }
        }
    }
}
